/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#ifndef __BASE_TYPE_H__
#define __BASE_TYPE_H__

#include <stdio.h>
#include <iostream>
#include <functional>
#include <vector>
#include <memory>
using namespace std;
namespace libemb{
/**
 *	\file  BaseType.h
 *	\brief
 */
class BaseInfo{
private:
	static const int m_major=2;/* 主版本 */
	static const int m_minor=0;/* 小版本 */
	static const int m_patch=0;/* 补丁版本 */
public:
	static const int verMajor();
	static const int verMinor();
	static const int verPatch();
	static std::string version();
};

using sint8 = signed char;
using sint16 = signed short;
using sint32 = signed int;
using sint64 = signed long long;
using uint8 = unsigned char;
using uint16 = unsigned short;
using uint32 = unsigned int;
using uint64 = unsigned long long;

/** 定义函数返回值 */
enum RC_E
{
    RC_OK = 0,      /**< 返回值:正常 */
    RC_ERROR = -1,  /**< 返回值:出错 */
    RC_TIMEOUT = -2,/**< 返回值:超时 */
};

/** 定义数据类型 */
enum BASETYPE_E
{
    BASETYPE_NONE=0,        /**< 未知类型 */
    BASETYPE_INT,           /**< 整数 */
    BASETYPE_DOUBLE,        /**< 浮点数 */
    BASETYPE_STRING,        /**< 字符串 */
    BASETYPE_INTARRAY,      /**< 整数数组 */
    BASETYPE_DOUBLEARRAY,   /**< 浮点数数组 */
    BASETYPE_STRINGARRAY,   /**< 字符串数组 */
    BASETYPE_TUPLE,         /**< 元组 */
};
}

/** 计算数组大小(元素个数) \a array.*/
#define ARRAY_SIZE(array)   (sizeof(array)/sizeof(array[0]))    

/** 判断一个字符是否是十进制数字 \a ch.*/
#define IS_DIGITAL(ch)   ((((ch)>='0')&&((ch)<='9'))?true:false)

/** 判断一个字符是否是16进制数字 \a ch.*/
#define IS_HEXDIG(ch)    (((((ch)>='0')&&((ch)<='9'))||(((ch)>='A')&&((ch)<='F'))||(((ch)>='a')&&((ch)<='f')))?true:false)

/** 判断一个字符是否是大写字母 \a ch.*/
#define IS_CAPITAL(ch)   ((((ch)>='A')&&((ch)<='Z'))?true:false)

/** 判断一个字符是否是字母 \a ch.*/
#define IS_ALPHABET(ch)  (((((ch)>='A')&&((ch)<='Z'))||(((ch)>='a')&&((ch)<='b')))?true:false)

/** 返回 \a x 和 \a y 中较大值. */
#define MAX(x,y) (((x)>(y))?(x):(y))

/** 返回 \a x 和 \a y 中较小值. */
#define MIN(x,y) (((x)<(y))?(x):(y))

/** 在 \a min 和 \a max 区间中取与 \a x 大小较接近的数值. */
#define CLIP(min,x,max) (((x)>(max))?(max):(((x)<(min))?(min):(x)))

#define PI              	(3.1415926)     /**< 圆周率. */
#define SQUARE(x)       	((x)*(x))       /**< \a x 的平方. */
#define R_AREA(r)       	((PI)*(r)*(r))  /**< 计算半径为\a r 的圆的面积. */

#define BIT_GET(value,bit)      (!!((0x0001<<(bit))&(value)))   /**< 获取value的第bit位的值 */
#define BIT_SET(value,bit)      ((0x0001<<(bit))|(value))       /**< 设置value的第bit位的值 */
#define BIT_CLR(value,bit)      ((~(0x0001<<(bit)))&(value))    /**< 清除value的第bit位的值 */

#define UNUSED_PARAM(param) {(void)(param);}                  	/**< 消除未使用变量警告 */
#define CSTR(stdstr)		((stdstr).c_str())		
#define CH2STR(ch)			(std::string(1,(char)ch))
#define BUILD_DATE          __DATE__
#define BUILD_TIME          __TIME__

/** 禁止对象拷贝(删除拷贝构造函数和赋值运算符) */
#define DECL_COPY_DISABLE(...) \
  __VA_ARGS__(const __VA_ARGS__ &) = delete; \
  __VA_ARGS__ & operator=(const __VA_ARGS__ &) = delete;

#define ENUM_STRING(enum_name)  {enum_name,#enum_name}    /**< 定义枚举字符串 */
struct EnumString{
    int value;
    const char *name;
};

/** 动态链接库的符号导出控制,在声明的时候加上即可 */
#if __GNUC__ >= 4
	#define SYMBOL_PUBLIC __attribute__ ((visibility("default")))
	#define SYMBOL_LOCAL  __attribute__ ((visibility("hidden")))
#else
	#define SYMBOL_PUBLIC
	#define SYMBOL_LOCAL
#endif


namespace libemb{
/**
 *  \file   BaseType.h   
 *  \class  Array
 *  \brief  抽象数组类	
 */

template <typename T>
class Array{
public:
    Array():m_type(BASETYPE_NONE){}
    virtual ~Array()
	{
		m_array.clear();
	}
	int type()
	{
		return m_type;
	}
	int size()
    {
		return m_array.size();
	}
    void clear()
	{
		m_array.clear();
	}
    T& operator[](int idx)
    {
		return m_array[idx];
	}
    Array& operator=(const Array& array)
    {
		if (this==&array)
	    {
	        return (*this);
	    }
	    m_array = array.m_array;
	    return (*this);
	}
    Array& append(T item)
    {
		m_array.push_back(item);
	    return *this;
	}
protected:
    int m_type;
	std::vector<T> m_array;
};

/**
 *  \file   BaseType.h   
 *  \class  IntArray
 *  \brief  整型数组类,例:[1, 2, 3]
 */
class IntArray:public Array<int>{
public:
	IntArray()
	{
		m_type = BASETYPE_INTARRAY;
	}
	IntArray(const std::string& arrayString)
	{
		m_type = BASETYPE_INTARRAY;
		initWithString(arrayString);
	}
    bool initWithString(const std::string& arrayString);
    std::string serialize();
	friend std::ostream& operator<<(std::ostream& os,IntArray& array)
	{
		os<<array.serialize();
		return os;
	}
};

/**
 *  \file   BaseType.h   
 *  \class  DoubleArray
 *  \brief  浮点型数组类,例:[1.01, 2.02, 3.03]
 */
class DoubleArray:public Array<double>{
public:
	DoubleArray()
	{
		m_type = BASETYPE_DOUBLEARRAY;
	}
	DoubleArray(const std::string& arrayString)
	{
		m_type = BASETYPE_DOUBLEARRAY;
		initWithString(arrayString);
	}
    bool initWithString(const std::string& arrayString);
    std::string serialize();
	friend std::ostream& operator<<(std::ostream& os,DoubleArray& array)
	{
		os<<array.serialize();
		return os;
	}
};

/**
 *  \file   BaseType.h   
 *  \class  StringArray
 *  \brief  字符串型数组类,例:["one", "two", "three"]	
 */
class StringArray:public Array<std::string>{
public:
	StringArray()
	{
		m_type = BASETYPE_STRINGARRAY;
	}
	StringArray(const std::string& arrayString)
	{
		m_type = BASETYPE_STRINGARRAY;
		initWithString(arrayString);
	}
    bool initWithString(const std::string& arrayString);
    std::string serialize();
	friend std::ostream& operator<<(std::ostream& os,StringArray& array)
	{
		os<<array.serialize();
		return os;
	}
};

/**
 *  \file   BaseType.h   
 *  \class  TupleItem
 *  \brief  元组元素	
 */
 
class TupleItem{
public:
    TupleItem(int);
    TupleItem(double);
    TupleItem(std::string);
    TupleItem(const TupleItem&);
    virtual ~TupleItem();
    int baseType();
    int toInt();
    double toDouble();
    std::string toString();
private:
    int m_type;
    double m_value;
    std::string m_string;
};

/**
 *  \file   BaseType.h   
 *  \class  Tuple
 *  \brief  元组	类,可以同时存储整数、浮点数和字符串,例:(1, 3.14159, "tuple")
 */
class Tuple{
public:
    Tuple();
    Tuple(const Tuple&);
    virtual ~Tuple();
    bool initWithString(const std::string& tupleString);
    int size();
    int type();
    void clear();
    std::string serialize();
	template <typename T>
    Tuple& append(T& item)
	{
		auto itemPtr = std::make_unique<TupleItem>(item);
	    m_itemVect.push_back(std::move(itemPtr));
	    return *this;
	}
	template <typename T>
    Tuple& insert(int idx, T& item)
    {
		auto itemPtr = std::make_unique<TupleItem>(item);	
	    auto iter = m_itemVect.begin();
	    int vsize = m_itemVect.size();
	    for (auto i=0; i<idx && i<vsize; i++) 
	    {
	        iter++;
	    }
	    m_itemVect.insert(iter, std::move(itemPtr));
	    return *this;
	}
    TupleItem& operator[](int idx);
    Tuple& operator=(const Tuple&);
    friend std::ostream& operator<<(std::ostream& os,Tuple& tuple)
	{
		os << tuple.serialize();
		return os;
	}
private:
    std::vector<std::unique_ptr<TupleItem>> m_itemVect;
};
}
#endif
